using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Windows.Forms;
using System.Xml;

namespace SoftManager
{
    /// <summary>
    /// 自动更新帮助类
    /// </summary>
    public class AutoUpdateHelper
    {
        private string _updateUrl = ""; // 更新服务器地址
        private string _appName = "SoftManager"; // 应用程序名称
        private string _appVersion = "1.0.0"; // 当前版本
        private Form _parentForm; // 父窗体，用于显示进度

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="updateUrl">更新服务器地址</param>
        /// <param name="appName">应用程序名称</param>
        /// <param name="currentVersion">当前版本</param>
        /// <param name="parentForm">父窗体</param>
        public AutoUpdateHelper(string updateUrl, string appName, string currentVersion, Form parentForm)
        {
            _updateUrl = updateUrl;
            _appName = appName;
            _appVersion = currentVersion;
            _parentForm = parentForm;
        }

        /// <summary>
        /// 检查更新并自动安装（无需用户确认，用于程序启动前）
        /// </summary>
        /// <returns>是否有新版本并开始更新</returns>
        public bool CheckUpdateAndAutoInstallBeforeStart()
        {
            try
            {
                // 下载更新信息文件
                string updateInfoUrl = $"{_updateUrl}/update.xml";
                string updateInfo = DownloadFile(updateInfoUrl);

                if (string.IsNullOrEmpty(updateInfo))
                {
                    return false;
                }

                // 解析更新信息
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.LoadXml(updateInfo);

                XmlNodeList nodeList = xmlDoc.SelectNodes("//Update");
                if (nodeList == null || nodeList.Count == 0)
                {
                    return false;
                }

                string latestVersion = nodeList[0].Attributes["Version"].Value;
                string downloadUrl = nodeList[0].Attributes["DownloadUrl"].Value;

                // 比较版本号
                if (CompareVersion(_appVersion, latestVersion) < 0)
                {
                    // 直接开始更新，不提示用户
                    DownloadAndUpdateBeforeStart(downloadUrl);
                    return true;
                }

                return false;
            }
            catch (Exception ex)
            {
                // 静默处理错误，不显示给用户
                Console.WriteLine($"启动前自动检查更新失败：{ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 下载并更新（用于程序启动前）
        /// </summary>
        /// <param name="downloadUrl">下载地址</param>
        private void DownloadAndUpdateBeforeStart(string downloadUrl)
        {
            try
            {
                // 创建临时目录
                string tempPath = Path.Combine(Path.GetTempPath(), _appName + "_Update");
                if (!Directory.Exists(tempPath))
                {
                    Directory.CreateDirectory(tempPath);
                }

                string updateFileName = Path.GetFileName(downloadUrl);
                string updateFilePath = Path.Combine(tempPath, updateFileName);

                // 同步下载文件（不显示进度条）
                WebClient client = new WebClient();
                client.DownloadFile(downloadUrl, updateFilePath);

                // 执行更新
                ExecuteUpdateBeforeStart(updateFilePath);
            }
            catch (Exception ex)
            {
                // 静默处理错误，不显示给用户
                Console.WriteLine($"启动前下载更新失败：{ex.Message}");
            }
        }

        /// <summary>
        /// 执行更新（用于程序启动前）
        /// </summary>
        /// <param name="updateFilePath">更新文件路径</param>
        private void ExecuteUpdateBeforeStart(string updateFilePath)
        {
            try
            {
                // 获取当前程序目录和可执行文件路径
                string appPath = Application.StartupPath;
                string appExePath = Application.ExecutablePath;
                
                // 获取Updater.exe路径
                string updaterPath = Path.Combine(appPath, "Updater", "Updater.exe");
                
                // 如果Updater.exe不存在，使用传统批处理方式
                if (!File.Exists(updaterPath))
                {
                    ExecuteUpdateWithBatch(updateFilePath);
                    return;
                }
                
                // 构建Updater.exe的命令行参数
                string arguments = $"/updateFile:\"{updateFilePath}\" /targetExe:\"{appExePath}\" /targetApp:\"{appPath}\"";
                
                // 启动Updater.exe
                ProcessStartInfo startInfo = new ProcessStartInfo
                {
                    FileName = updaterPath,
                    Arguments = arguments,
                    UseShellExecute = true,
                    CreateNoWindow = false,
                    WindowStyle = ProcessWindowStyle.Normal
                };

                Process.Start(startInfo);
            }
            catch (Exception ex)
            {
                // 静默处理错误，不显示给用户
                Console.WriteLine($"启动前执行更新失败：{ex.Message}");
            }
        }

        /// <summary>
        /// 检查更新并自动安装（无需用户确认）
        /// </summary>
        /// <returns>是否有新版本并开始更新</returns>
        public bool CheckUpdateAndAutoInstall()
        {
            try
            {
                // 下载更新信息文件
                string updateInfoUrl = $"{_updateUrl}/update.xml";
                string updateInfo = DownloadFile(updateInfoUrl);

                if (string.IsNullOrEmpty(updateInfo))
                {
                    return false;
                }

                // 解析更新信息
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.LoadXml(updateInfo);

                XmlNodeList nodeList = xmlDoc.SelectNodes("//Update");
                if (nodeList == null || nodeList.Count == 0)
                {
                    return false;
                }

                string latestVersion = nodeList[0].Attributes["Version"].Value;
                string downloadUrl = nodeList[0].Attributes["DownloadUrl"].Value;
                string updateLog = nodeList[0].Attributes["UpdateLog"].Value;

                // 比较版本号
                if (CompareVersion(_appVersion, latestVersion) < 0)
                {
                    // 直接开始更新，不提示用户
                    DownloadAndUpdate(downloadUrl);
                    return true;
                }

                return false;
            }
            catch (Exception ex)
            {
                // 静默处理错误，不显示给用户
                Console.WriteLine($"自动检查更新失败：{ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 检查更新
        /// </summary>
        /// <returns>是否有新版本</returns>
        public bool CheckUpdate()
        {
            try
            {
                // 下载更新信息文件
                string updateInfoUrl = $"{_updateUrl}/update.xml";
                string updateInfo = DownloadFile(updateInfoUrl);

                if (string.IsNullOrEmpty(updateInfo))
                {
                    return false;
                }

                // 解析更新信息
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.LoadXml(updateInfo);

                XmlNodeList nodeList = xmlDoc.SelectNodes("//Update");
                if (nodeList == null || nodeList.Count == 0)
                {
                    return false;
                }

                string latestVersion = nodeList[0].Attributes["Version"].Value;
                string downloadUrl = nodeList[0].Attributes["DownloadUrl"].Value;
                string updateLog = nodeList[0].Attributes["UpdateLog"].Value;

                // 比较版本号
                if (CompareVersion(_appVersion, latestVersion) < 0)
                {
                    // 显示更新提示
                    DialogResult result = MessageBox.Show(
                        $"发现新版本 {latestVersion}\n\n更新内容：\n{updateLog}\n\n是否立即更新？",
                        "发现新版本",
                        MessageBoxButtons.YesNo,
                        MessageBoxIcon.Information);

                    if (result == DialogResult.Yes)
                    {
                        // 开始更新
                        DownloadAndUpdate(downloadUrl);
                        return true;
                    }
                }
                else
                {
                    MessageBox.Show("当前已是最新版本！", "检查更新", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }

                return false;
            }
            catch (Exception ex)
            {
                MessageBox.Show($"检查更新失败：{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }
        }

        /// <summary>
        /// 下载并更新
        /// </summary>
        /// <param name="downloadUrl">下载地址</param>
        private void DownloadAndUpdate(string downloadUrl)
        {
            try
            {
                // 创建临时目录
                string tempPath = Path.Combine(Path.GetTempPath(), _appName + "_Update");
                if (!Directory.Exists(tempPath))
                {
                    Directory.CreateDirectory(tempPath);
                }

                string updateFileName = Path.GetFileName(downloadUrl);
                string updateFilePath = Path.Combine(tempPath, updateFileName);

                // 显示下载进度
                ProgressBarForm progressForm = new ProgressBarForm("正在下载更新...");
                progressForm.Show(_parentForm);

                // 异步下载文件
                WebClient client = new WebClient();
                client.DownloadProgressChanged += (sender, e) =>
                {
                    progressForm.UpdateProgress(e.ProgressPercentage, $"正在下载... {e.ProgressPercentage}%");
                };
                client.DownloadFileCompleted += (sender, e) =>
                {
                    progressForm.Close();

                    if (e.Error != null)
                    {
                        MessageBox.Show($"下载失败：{e.Error.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        return;
                    }

                    // 执行更新
                    ExecuteUpdate(updateFilePath);
                };

                client.DownloadFileAsync(new Uri(downloadUrl), updateFilePath);
            }
            catch (Exception ex)
            {
                MessageBox.Show($"下载更新失败：{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// 执行更新
        /// </summary>
        /// <param name="updateFilePath">更新文件路径</param>
        private void ExecuteUpdate(string updateFilePath)
        {
            try
            {
                // 获取当前程序目录和可执行文件路径
                string appPath = Application.StartupPath;
                string appExePath = Application.ExecutablePath;
                
                // 获取Updater.exe路径
                string updaterPath = Path.Combine(appPath, "Updater", "Updater.exe");
                
                // 如果Updater.exe不存在，使用传统批处理方式
                if (!File.Exists(updaterPath))
                {
                    ExecuteUpdateWithBatch(updateFilePath);
                    return;
                }
                
                // 构建Updater.exe的命令行参数
                string arguments = $"/updateFile:\"{updateFilePath}\" /targetExe:\"{appExePath}\" /targetApp:\"{appPath}\"";
                
                // 启动Updater.exe
                ProcessStartInfo startInfo = new ProcessStartInfo
                {
                    FileName = updaterPath,
                    Arguments = arguments,
                    UseShellExecute = true,
                    CreateNoWindow = false,
                    WindowStyle = ProcessWindowStyle.Normal
                };

                Process.Start(startInfo);

                // 关闭当前程序
                Application.Exit();
            }
            catch (Exception ex)
            {
                MessageBox.Show($"执行更新失败：{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// 使用批处理方式执行更新（备用方案）
        /// </summary>
        /// <param name="updateFilePath">更新文件路径</param>
        private void ExecuteUpdateWithBatch(string updateFilePath)
        {
            try
            {
                // 获取当前程序目录和可执行文件路径
                string appPath = Application.StartupPath;
                string appExePath = Application.ExecutablePath;
                string appExeName = Path.GetFileName(appExePath);
                
                // 创建更新批处理文件
                string batchPath = Path.Combine(Path.GetTempPath(), "Update_" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".bat");
                
                using (StreamWriter writer = new StreamWriter(batchPath))
                {
                    writer.WriteLine("@echo off");
                    writer.WriteLine("echo 正在更新，请稍候...");
                    writer.WriteLine("timeout /t 2 /nobreak > nul");
                    
                    // 结束当前运行的程序
                    writer.WriteLine($"taskkill /f /im \"{appExeName}\" > nul 2>&1");
                    
                    // 等待程序完全关闭
                    writer.WriteLine("timeout /t 2 /nobreak > nul");
                    
                    // 备份当前程序（可选）
                    string backupPath = Path.Combine(appPath, appExeName + ".bak");
                    writer.WriteLine($"if exist \"{appExePath}\" copy /Y \"{appExePath}\" \"{backupPath}\" > nul 2>&1");
                    
                    // 解压更新文件（如果是zip文件）
                    if (Path.GetExtension(updateFilePath).ToLower() == ".zip")
                    {
                        writer.WriteLine("echo 正在解压更新文件...");
                        // 使用PowerShell解压文件
                        writer.WriteLine($"powershell -Command \"Expand-Archive -Path '{updateFilePath}' -DestinationPath '{appPath}' -Force\"");
                    }
                    else
                    {
                        // 直接复制文件
                        writer.WriteLine("echo 正在替换文件...");
                        writer.WriteLine($"copy /Y \"{updateFilePath}\" \"{appExePath}\" > nul 2>&1");
                    }
                    
                    // 检查更新是否成功
                    writer.WriteLine($"if not exist \"{appExePath}\" (");
                    writer.WriteLine("    echo 更新失败！无法找到更新后的程序文件。");
                    writer.WriteLine("    pause");
                    writer.WriteLine("    exit /b 1");
                    writer.WriteLine(")");
                    
                    writer.WriteLine("echo 更新成功！");
                    writer.WriteLine("echo 正在启动程序...");
                    
                    // 启动更新后的程序
                    writer.WriteLine($"start \"\" \"{appExePath}\"");
                    
                    // 清理临时文件
                    writer.WriteLine($"timeout /t 2 /nobreak > nul");
                    writer.WriteLine($"del \"{updateFilePath}\" > nul 2>&1");
                    writer.WriteLine($"del \"%~f0\" > nul 2>&1");
                    
                    writer.WriteLine("exit");
                }
                
                // 启动批处理文件
                ProcessStartInfo startInfo = new ProcessStartInfo
                {
                    FileName = batchPath,
                    UseShellExecute = true,
                    CreateNoWindow = false,
                    WindowStyle = ProcessWindowStyle.Normal
                };

                Process.Start(startInfo);

                // 关闭当前程序
                Application.Exit();
            }
            catch (Exception ex)
            {
                MessageBox.Show($"执行更新失败：{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// 下载文件
        /// </summary>
        /// <param name="url">文件URL</param>
        /// <returns>文件内容</returns>
        private string DownloadFile(string url)
        {
            try
            {
                using (WebClient client = new WebClient())
                {
                    return client.DownloadString(url);
                }
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        /// 比较版本号
        /// </summary>
        /// <param name="version1">版本1</param>
        /// <param name="version2">版本2</param>
        /// <returns>-1: version1 < version2, 0: version1 = version2, 1: version1 > version2</returns>
        private int CompareVersion(string version1, string version2)
        {
            string[] v1 = version1.Split('.');
            string[] v2 = version2.Split('.');

            int len = Math.Max(v1.Length, v2.Length);
            for (int i = 0; i < len; i++)
            {
                int num1 = i < v1.Length ? int.Parse(v1[i]) : 0;
                int num2 = i < v2.Length ? int.Parse(v2[i]) : 0;

                if (num1 < num2)
                    return -1;
                else if (num1 > num2)
                    return 1;
            }

            return 0;
        }
    }

    /// <summary>
    /// 进度条窗体
    /// </summary>
    public class ProgressBarForm : Form
    {
        private ProgressBar progressBar;
        private Label labelStatus;

        public ProgressBarForm(string title)
        {
            this.Text = title;
            this.Size = new System.Drawing.Size(400, 150);
            this.FormBorderStyle = FormBorderStyle.FixedDialog;
            this.StartPosition = FormStartPosition.CenterParent;
            this.MaximizeBox = false;
            this.MinimizeBox = false;
            this.ControlBox = false;

            progressBar = new ProgressBar
            {
                Location = new System.Drawing.Point(20, 50),
                Size = new System.Drawing.Size(360, 23),
                Style = ProgressBarStyle.Continuous
            };

            labelStatus = new Label
            {
                Location = new System.Drawing.Point(20, 20),
                Size = new System.Drawing.Size(360, 23),
                Text = "准备中..."
            };

            this.Controls.Add(progressBar);
            this.Controls.Add(labelStatus);
        }

        public void UpdateProgress(int percent, string status)
        {
            if (progressBar.InvokeRequired)
            {
                progressBar.Invoke(new Action(() => UpdateProgress(percent, status)));
                return;
            }

            progressBar.Value = percent;
            labelStatus.Text = status;
            this.Update();
        }
    }
}